<?php

namespace Helpers;

use Endroid\QrCode\QrCode;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

class Tool
{

    /**
     * 检查是否为windows系统
     *
     * @return bool
     *
     * create by ck 20170808
     */
    public static function isWindows()
    {
        return PATH_SEPARATOR == ';';
    }

    /**
     * 根据传入参数，组成路径返回
     *
     * @param $args
     * @return string
     *
     * create by ck 20170808
     * modify by ck 20181212    忽略无效参数
     */
    public static function buildPath($args)
    {
        $args = func_get_args();
        $path = [];
        for ($i = 0; $i < func_num_args(); $i++) {
            if (!$args[$i]) {
                continue;
            }
            $path[] = rtrim($args[$i], '/');
        }
        return implode('/', $path);
    }

    /**
     * 获取结尾时间
     *
     * @param $date
     * @param bool $timestamp
     * @return false|int|string
     *
     * create by ck 20180918
     */
    public static function getEndTime($date, $timestamp = true)
    {
        $date = strtotime($date . ' +1 day');
        return $timestamp ? $date : date('Y-m-d H:i:s', $date);
    }

    /**
     * 除法，除数为0则返回0
     *
     * @param $a
     * @param $b
     * @param int $precision
     * @return float|int
     *
     * create by ck 20180928
     */
    public static function division($a, $b, $precision = 1)
    {
        if ($b == 0) {
            return 0;
        }
        return @round($a / $b, $precision);
    }

    /**
     * 验证是否为手机号
     *
     * @param string $phone
     * @return int
     *
     * create by ck 20190225
     */
    public static function validPhone(string $phone)
    {
        return preg_match('/^1[3456789]{1}\d{9}$/', $phone);
    }

    /**
     * 构建url
     *
     * @param string $path
     * @param array $params
     * @param string $scheme
     * @return string
     *
     * create by ck 20171214
     * modify by ck 20180413
     * modify by ck 20180824    更改方式
     */
    public static function buildUrl($path = '', $params = [], $scheme = '')
    {
        $scheme = $scheme ?: $_SERVER['REQUEST_SCHEME'];
//        $serverName = $_SERVER['SERVER_NAME'];
        $urlInfo = parse_url($_SERVER['HTTP_HOST']);
        $serverName = isset($urlInfo['host']) ? $urlInfo['host'] : $urlInfo['path'];
//        $port       = ':' . $_SERVER['SERVER_PORT'];
        $port = self::getValue($urlInfo, 'port');
        $baseUrl = preg_replace('/(public)*([\/\\\\])index.php$/', '', $_SERVER["PHP_SELF"]) ?: '/';
        if (($scheme == 'http' && $port == 80) || ($scheme == 'https' && $port == 443)) {
            $port = '';
        } elseif ($port) {
            $port = ':' . $port;
        }
        $params = $params ? ('?' . http_build_query($params)) : '';
        return $scheme . '://' . $serverName . $port . $baseUrl . ltrim($path, '/') . $params;
    }

    /**
     * 检查数组中key是否存在并返回
     *
     * @param array $array
     * @param string $key
     * @param string $default
     * @param null $callback
     * @return mixed|string
     *
     * create by ck 20180419
     * modify by ck 20181120
     */
    public static function getValue($array, $key, $default = '', $callback = null)
    {
        if (!is_array($array)) {
            return $default;
        }
        return array_key_exists($key, $array)
            ? ($callback
                ? call_user_func($callback, $array[$key])
                : $array[$key])
            : $default;
    }

    /**
     * 数组键值替换
     *
     * @param $obj
     * @param array $keys
     * @param bool $deep
     *
     * create by ck 20171228
     */
    public static function replaceKey(&$obj, $keys = [], $deep = true)
    {
        foreach ($obj as $key => &$value) {
            if ($deep && is_array($value)) {
                self::replaceKey($value, $keys, $deep);
            }
            if (key_exists($key, $keys)) {
                $obj[$keys[$key]] = $value;
                unset($obj[$key]);
            }
        }
    }

    /**
     * 获取二维码(base64 Uri)
     *
     * @param $content
     * @return string
     *
     * create by ck 20181026
     * modify by ck 20181026    重构
     */
    public static function getQRBase64Uri($content)
    {
        return (new QrCode($content))->writeDataUri();
//        if ($base64) {
//            ob_start();
//        }
//        QRcode::png(
//            $content,
//            false,
//            self::getValue($params, 'level', 0),
//            self::getValue($params, 'size', 10),
//            self::getValue($params, 'margin', 1)
//        );
//        if ($base64) {
//            $img = base64_encode(ob_get_contents());
//            ob_end_clean();
//            return 'data:image/png;base64,' . $img;
//        }
    }

    /**
     * 处理excel内容数组
     *
     * @param $title
     * @param $data
     * @return array
     *
     * create by ck 20181122
     */
    public static function runExcelData($title, $data)
    {
        $keys = array_keys($title);
        $exportData = [];
        foreach ($data as $key => $row) {
            foreach ($keys as $field) {
                $exportData[$key][$field] = self::getValue($row, $field);
            }
        }
        return $exportData;
    }

    /**
     * 读取excel文件内容
     *
     * @param $fileName
     * @param bool $getAll
     * @param string $extension
     * @return array
     * @throws \Exception
     *
     * create by ck 20170808
     * modify by ck 20180507    支持传入扩展名
     * modify by ck 20180829    升级插件
     * modify by ck 20181030    修复列数获取错误bug
     */
    public static function readExcel($fileName, $getAll = false, $extension = '')
    {
//        require_once APP_PATH . '/common/library/PHPExcel/PHPExcel.php';
//        require_once APP_PATH . '/common/library/PHPExcel/PHPExcel/IOFactory.php';
        try {
            $extension or $extension = strtolower(pathinfo($fileName)['extension']);
            switch ($extension) {
                case 'xls':
//                    $excel = (new \PHPExcel_Reader_Excel5())->load($fileName);
                    $excel = IOFactory::createReader('Xls')->load($fileName);
                    break;
                case 'xlsx':
//                    $excel = (new \PHPExcel_Reader_Excel2007())->load($fileName);
                    $excel = IOFactory::createReader('Xlsx')->load($fileName);
                    break;
                case 'csv':
//                    $excel = (new \PHPExcel_Reader_CSV())->load($fileName);
                    $excel = IOFactory::createReader('Csv')->load($fileName);
                    break;
                default:
                    throw new \Exception('暂不支持该文件类型！');
            }
            $sheet = $excel->getSheet(0);
            $rowNum = $sheet->getHighestRow();
            $maxColumn = $sheet->getHighestColumn();    //AJ

            //计算列数
            $columnNum = 0;
            for ($i = 0; $i < strlen($maxColumn); $i++) {
                $columnNum and $columnNum += 25;
                $columnNum += (ord($maxColumn[$i]) - ord('A') + 1);
            }
            if (!$rowNum || !$columnNum) {
                throw new \Exception('文件内容为空！');
            }

            //表格头解析
            $title = [];
            for ($column = 1; $column <= $columnNum; $column++) {
                $title[] = $sheet->getCellByColumnAndRow($column, 1)->getCalculatedValue();
            }

            //表格数据读取
            $data = [];
            for ($row = 2; $row <= $rowNum; $row++) {
                for ($column = 1; $column <= $columnNum; $column++) {
                    $val = $sheet->getCellByColumnAndRow($column, $row)->getCalculatedValue();
                    if (is_object($val)) {
                        throw new \Exception(chr($column + ord('A')) . $row . '文本读取失败');
                    }
                    $data[$row - 2][$column - 1] = $val;
                }
            }
        } catch (\Exception $e) {
            throw new \Exception($e->getMessage());
        }
        return $getAll ? ['title' => $title, 'data' => $data] : $data;
    }

    public static function readExcelBySheet($fileName, $getAll = false, $sheetIndex = 0, $extension = '')
    {
//        require_once APP_PATH . '/common/library/PHPExcel/PHPExcel.php';
//        require_once APP_PATH . '/common/library/PHPExcel/PHPExcel/IOFactory.php';
        try {
            $extension or $extension = strtolower(pathinfo($fileName)['extension']);
            switch ($extension) {
                case 'xls':
//                    $excel = (new \PHPExcel_Reader_Excel5())->load($fileName);
                    $excel = IOFactory::createReader('Xls')->load($fileName);
                    break;
                case 'xlsx':
//                    $excel = (new \PHPExcel_Reader_Excel2007())->load($fileName);
                    $excel = IOFactory::createReader('Xlsx')->load($fileName);
                    break;
                case 'csv':
//                    $excel = (new \PHPExcel_Reader_CSV())->load($fileName);
                    $excel = IOFactory::createReader('Csv')->load($fileName);
                    break;
                default:
                    throw new \Exception('暂不支持该文件类型！');
            }
            $sheet = $excel->getSheet($sheetIndex);
            $rowNum = $sheet->getHighestRow();
            $maxColumn = $sheet->getHighestColumn();    //AJ

            //计算列数
            $columnNum = 0;
            for ($i = 0; $i < strlen($maxColumn); $i++) {
                $columnNum and $columnNum += 25;
                $columnNum += (ord($maxColumn[$i]) - ord('A') + 1);
            }
            if (!$rowNum || !$columnNum) {
                throw new \Exception('文件内容为空！');
            }

            //表格头解析
            $title = [];
            for ($column = 1; $column <= $columnNum; $column++) {
                $title[] = $sheet->getCellByColumnAndRow($column, 1)->getCalculatedValue();
            }

            //表格数据读取
            $data = [];
            for ($row = 2; $row <= $rowNum; $row++) {
                for ($column = 1; $column <= $columnNum; $column++) {
                    $val = $sheet->getCellByColumnAndRow($column, $row)->getCalculatedValue();
                    if (is_object($val)) {
                        throw new \Exception(chr($column + ord('A')) . $row . '文本读取失败');
                    }
                    $data[$row - 2][$column - 1] = $val;
                }
            }
        } catch (\Exception $e) {
            throw new \Exception($e->getMessage());
        }
        return $getAll ? ['title' => $title, 'data' => $data] : $data;
    }


    /**
     * 根据文件名，标题及数据生成Excel文档
     *
     * @param $fileName
     * @param $titleArr
     * @param $data
     * @param string $type
     * @param array $options
     * @throws \PHPExcel_Exception
     * @throws \PHPExcel_Reader_Exception
     *
     * create by ck 20160104
     * modify by ck 20170417    添加类型
     * modify by ck 20170426    设置单元格为文本，防止科学计数法
     * modify by ck 20170926    可设置options
     */
//    public static function exportExcelOnline($fileName, $titleArr, $data, $type = 'xlsx', $options = [])
//    {
//        $typeArr = [
//            'xlsx'  => 'Excel2007',
//            'xls'   => 'Excel5',
//            'csv'   => 'CSV',
//            'html'  => 'html'
//        ];
//        array_key_exists($type, $typeArr) or $type = 'xlsx';
//        require_once APP_PATH . '/common/library/PHPExcel/PHPExcel.php';
//        require_once APP_PATH . '/common/library/PHPExcel/PHPExcel/IOFactory.php';
//        $objPHPExcel = new \PHPExcel();
//        $objPHPExcel->setActiveSheetIndex(0);
//
//        $startRow = 1;
//        if(isset($options['header'])){
//            $startRow = 2;
//            $sheet = $objPHPExcel->getActiveSheet();
//            $sheet->getRowDimension(1)->setRowHeight(isset($options['header']['height']) ? $options['header']['height'] : 40);
//            $endChar = chr(ord('A')+count($titleArr)-1);
//            $sheet->mergeCells('A1:'.$endChar.'1');
//            $sheet->setCellValue('A1',  $options['header']['title']);
//            $sheet->getStyleByColumnAndRow('A', 1)->getFont()->setSize(isset($options['header']['fontSize']) ? $options['header']['fontSize'] : 18);
//            $sheet->getStyleByColumnAndRow('A', 1)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
//            $sheet->getStyleByColumnAndRow('A', 1)->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
//        }
//        //设置excel列名
//        $cell = 'A';
//        $bCell = '';
//
//        $maxLenArr = [];
//        foreach ($titleArr as $key => $title) {
//            if ($cell > 'Z') {
//                if ($bCell == '') {
//                    $bCell = 'A';
//                } else {
//                    $bCell++;
//                }
//                $cell = 'A';
//            }
//            $objPHPExcel->getActiveSheet()->setCellValue($bCell . $cell . $startRow, is_array($title) ? $title['name'] : $title);
//
//            if (isset($options['autoWidth']) && $options['autoWidth']) {
//                $maxLenArr[$cell] = strlen(is_array($title) ? $title['name'] : $title);
//            }
//            $cell++;
//        }
//
//        //把数据循环写入excel中
//        foreach($data as $key => $value){
//            $cell   = 'A';
//            $bCell  = '';
//            $key += $startRow+1;
//            foreach($value as $field => $val){
//                if($cell > 'Z'){
//                    if($bCell == '') {
//                        $bCell = 'A';
//                    }
//                    else{
//                        $bCell++ ;
//                    }
//                    $cell = 'A';
//                }
//                $objPHPExcel->getActiveSheet()->setCellValueExplicit($bCell . $cell . $key, $val);
//                if (isset($options['autoWidth']) && $options['autoWidth']) {
//                    $maxLenArr[$cell] = $maxLenArr[$cell] >= strlen($val) ? $maxLenArr[$cell] : strlen($val);
//                }
////                $objPHPExcel->getActiveSheet()->getStyle($cell . $key)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
////                $objPHPExcel->getActiveSheet()->getStyle($cell . $key)->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
//                $cell++ ;
//            }
//            if (isset($options['height']) && $options['height']) {
//                $objPHPExcel->getActiveSheet()->getRowDimension($key)->setRowHeight($options['height']);
//            }
//        }
//
//        //自动宽度或设置宽度时定义宽
//        if (isset($options['autoWidth']) || isset($options['setWidth'])) {
//            $cell = 'A';
//            $bCell = '';
//            foreach ($titleArr as $key => $title) {
//                if ($cell > 'Z') {
//                    if ($bCell == '') {
//                        $bCell = 'A';
//                    } else {
//                        $bCell++;
//                    }
//                    $cell = 'A';
//                }
//                $width = is_array($title) && isset($title['width']) ? $title['width']
//                    : (isset($options['width']) ? $options['width'] : $maxLenArr[$cell]);
//                $objPHPExcel->getActiveSheet()->getColumnDimension($cell)->setWidth($width);
//                $cell++;
//            }
//        }
//
//        //导出代码
//        $objPHPExcel->getActiveSheet()->setTitle($fileName);
//        $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, $typeArr[$type]);
//        $fileName = $fileName . '.' . $type;
//        header('Content-Type: application/vnd.ms-excel');
//        header('Content-Type: application/octet-stream');
//        header('Content-Disposition: attachment; filename="' . $fileName . '"');
//        header('Cache-Control: max-age=0');
//        $objWriter->save('php://output');
//    }

    /**
     * 新导出Excel
     *
     * @param $fileName
     * @param $titleArr
     * @param $data
     * @param string $type
     * @param array $options
     * @throws XhException
     *
     * create by dale  20180825
     */
    public static function exportExcelOnline($fileName, $titleArr, $data, $type = 'xlsx', $options = [])
    {
        try {
            $checkType = ['xls', 'xlsx'];
            in_array($type, $checkType) or $type = 'xlsx';
            $spreadsheet = new Spreadsheet();
            $worksheet = $spreadsheet->getActiveSheet();
            $startRow = 1;
            $endChar = chr(ord('A') + count($titleArr) - 1);
            if (isset($options['header'])) { //设置头部
                $startRow = 2;
                $worksheet->mergeCells('A1:' . $endChar . '1'); //合并
                $worksheet->getStyle('A1')->applyFromArray([
                    'font' => [
                        'bold' => true
                    ],
                    'alignment' => [
                        'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
                        'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER
                    ],
                ])->getFont()->setSize(isset($options['header']['fontSize']) ? $options['header']['fontSize'] : 18);
                $worksheet->getRowDimension('1')->setRowHeight(isset($options['header']['height']) ? $options['header']['height'] : 40); //设置行高
                $worksheet->setCellValueByColumnAndRow(1, 1, $options['header']['title']);
            }

//            $worksheet->getDefaultColumnDimension()->setWidth(30); //默认宽度
            if (isset($options['autoWidth'])) { //自适应宽度
                for ($i = 0; $i < count($titleArr); $i++) {
                    $worksheet->getColumnDimension(chr(ord('A') + $i))->setAutoSize(true);
                }
            }
            $cell = 1;
            foreach ($titleArr as $key => $title) {
                $worksheet->setCellValueByColumnAndRow($cell, $startRow, is_array($title) ? $title['name'] : $title);
                $cell++;
            }
//            $startRow = $startRow +1;
//            $row = 0;
//            foreach ($data as $key => $value) {
//                $cell = 1;
//                $nowRow = $startRow + $row;
//                foreach ($value as $field => $val) {
//                    $worksheet->setCellValueByColumnAndRow($cell, $nowRow, $val,DataType::TYPE_STRING);
//                    $cell++;
//                }
//                $row++;
//            }
//            var_dump($startRow);die;
            foreach ($data as $key => $value) {
                $cell = 'A';
                $bCell = '';
//                var_dump($key);
//                var_dump($startRow);die;
                $key += $startRow + 1;
                foreach ($value as $field => $val) {
                    if ($cell > 'Z') {
                        if ($bCell == '') {
                            $bCell = 'A';
                        } else {
                            $bCell++;
                        }
                        $cell = 'A';
                    }
                    $worksheet->setCellValueExplicit($bCell . $cell . $key, $val, DataType::TYPE_STRING);
//                    $worksheet->getStyle($bCell . $cell . $key)->getAlignment()->setWrapText(true);
                    $cell++;
                }
                if (isset($options['height']) && $options['height']) {
                    $worksheet->getRowDimension($key)->setRowHeight($options['height']);
                }
            }

            //导出代码
            $worksheet->setTitle($fileName);
            $fileName = $fileName.'.'.$type;
            if ($type == 'xlsx') {
                header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
                $type = 'Xlsx';
            } elseif ($type == 'xls') {
                header('Content-Type: application/vnd.ms-excel');
            }
            header('Content-Type: application/octet-stream');
            header('Content-Disposition: attachment;filename="'.$fileName.'"');
            header('Cache-Control: max-age=0');
            $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, $type);
            $writer->save('php://output');
        } catch (\Exception $e) {
                throw new XhException($e->getMessage());
        }
    }

    /**
     * 设置excel数据
     *
     * @param Worksheet $worksheet
     * @param array $data
     * @param int $rowNum
     *
     * create by ck 20181207
     */
    public static function setExcelData(Worksheet $worksheet, $data = [], $rowNum = 1)
    {
        $startRowIndex = $rowNum - 1;
        foreach ($data as $key => $row) {
            $cell = 'A';
            $bCell = '';
            $key += $startRowIndex + 1;
            foreach ($row as $val) {
                if ($cell > 'Z') {
                    if ($bCell == '') {
                        $bCell = 'A';
                    } else {
                        $bCell++;
                    }
                    $cell = 'A';
                }
                $worksheet->setCellValueExplicit($bCell . $cell . $key, $val, DataType::TYPE_STRING);
                if ($key == 1) {
                    $worksheet->getColumnDimension($bCell . $cell . $key)->setAutoSize(true);
                }
                $cell++;
            }
        }
    }


    /**
     * 根据$convertTitleArr替换excel源数据
     *
     * @param $filePath
     * @param $convertTitleArr ['设备号' => 'code', '设备类型' => 'type']
     * @param int $sheetIndex  页签index 从 0开始
     *
     * @return array  ['code' => 'aaa', 'type' => 'bbbb']
     * @throws \Exception
     *
     * create by dale  20181220
     */
    public static function getExcelFieldDataByTitle($filePath, $convertTitleArr, $sheetIndex = 0)
    {
        if (!file_exists($filePath)) {
            throw new \Exception('文件不存在');
        }
        ini_set('memory_limit', '500M');
        $dataSource = Tool::readExcelBySheet($filePath, true, $sheetIndex);
        $indexTitleArr = @$dataSource['title'];
        $data = @$dataSource['data'];
        $data = array_filter(
            $data,
            function ($val) {
                if ($val[0]) {
                    return true;
                }
            }
        );
        $filedIndexArr = []; //字段和index对应关系数组
        foreach ($indexTitleArr as $index => $title) {
            $field = Tool::getValue($convertTitleArr, $title, null);
            if ($field) {
                $filedIndexArr[$field] = $index;
            }
        }
        unset($convertTitleArr);
        unset($indexTitleArr);
        if (!$filedIndexArr) {
            throw new \Exception('excel格式不对');
        }
        $filedArr = array_flip($filedIndexArr); // index => $filed
        $needKeys = array_keys($filedArr);
        $newSource = [];
        foreach ($data as $index => $row) {
            $arr = [];
            foreach ($row as $key => $value) {
                if (in_array($key, $needKeys)) {
                    $arr[$filedArr[$key]] = $value;
                }
            }
            unset($data[$index]);
            $newSource[] = $arr;
        }
        return $newSource;
    }


    /**
     * 发送短信
     *
     * @param $phoneNum
     * @param $msg
     * @return bool
     *
     * create by ck 20170428
     */
    public static function sendMsgToPhone($phoneNum, $msg)
    {
        $sendUrl = "http://www.100fen.com:8800/?user=xuehai&password=xuehai12345678&phonenumber=^TEL^&text=^MESSAGE^&charset=^CHARSET^";
        $sendSuccessContent = "信息已提交到发送队列";
        $sendUrl = str_replace("^TEL^", $phoneNum, $sendUrl);
        $sendUrl = str_replace("^MESSAGE^", urlencode($msg), $sendUrl);
        $result = file_get_contents($sendUrl);
        $sendSuccessContent = mb_convert_encoding($sendSuccessContent, 'gb2312', 'UTF-8');
        $pos1 = strpos($result, $sendSuccessContent);
        return $pos1 === false ? false : true;
    }

    /**
     * 发送邮件（支持附件）
     *
     * @param $address
     * @param array $option
     * @return bool|string
     * @throws phpmailerException
     *
     * create by ck 20170504
     * modify by ck 20170605    替换发送邮件方法
     */
    public static function sendMsgToMail($address, $option = [])
    {
        if (empty($address)) {
            return '地址不能为空！';
        }
        if (!isset($option['title'])) {
            return '标题不能为空！';
        }
        if (empty($option['content'])) {
            return '内容不能为空！';
        }

        Main::createCommitLog('word', 'exam', 'email', ['address' => $address, 'option' => $option], null, '发送邮件参数');
//        $sendParams = [
//            'address' => $address,
//            'title'   => $option['title'],
//            'content' => $option['content']
//        ];
//        if(isset($option['attachment'])){
//            $attachments = $option['attachment'];
//            is_string($attachments) and $attachments = [$attachments];
//            foreach($attachments as $index => $attachment){
//                if(PATH_SEPARATOR == ';'){
//                    $attachment = iconv('utf-8', 'GBK', $attachment);
//                }
//                $sendParams['file' . $index] = new \CURLFile(realpath($attachment));
//            }
//        }
//        $httpClient = new HttpClient('http://msg.aichenk.com');
//        $response   = $httpClient->setTimeout(0)->post('email', $sendParams);
//        if(!$response->isSuccess()) return false;
//        $body = $response->toObject();
//        if($body->code == 200) return true;
//        return $body->error;

        set_time_limit(0);
        ignore_user_abort(true);
        ini_set('magic_quotes_runtime', 0);
        $config = Main::getConfigByName('mailInfo');
        $mail = new PHPMailer(true);
        $mail->IsSMTP();
        $mail->CharSet = 'utf-8';
        $mail->SMTPAuth = true;                  //开启认证
        $mail->SMTPSecure = isset($config['secure']) ? $config['secure'] : 'ssl';
        $mail->Port = isset($config['port']) ? $config['port'] : 465;
        $mail->Host = $config['host'];
        $mail->Username = $config['username'];
        $mail->Password = $config['password'];
        $mail->From = $config['username'];
        $mail->FromName = isset($config['name']) ? $config['name'] : $config['username'];
        $mail->Subject = $option['title'];
        $mail->Body = $option['content'];
        is_string($address) and $address = [$address];
        foreach ($address as $add) {
            $mail->AddAddress($add);
        }
        if (isset($option['attachment'])) {
            $attachments = $option['attachment'];
            is_string($attachments) and $attachments = [$attachments];
            foreach ($attachments as $attachment) {
                if (PATH_SEPARATOR == ';') {
                    $attachment = iconv('utf-8', 'GBK', $attachment);
                }
                $mail->AddAttachment($attachment);
            }
        }
        if (isset($option['html']) && $option['html'] == true) {
            $mail->IsHTML(true);
        }
        try {
            $result = $mail->Send();
        } catch (\Exception $e) {
            return $e->getMessage();
        }
        return $result;
    }

    /**
     * 解密数据--学海接口规范
     *
     * @param $data
     * @param int $flag
     * @return string
     *
     * create by ck 20170219
     */
    public static function unZipData($data, $flag = 0)
    {
        switch ($flag) {
            case 1:
                return gzuncompress(base64_decode($data));
            default:
                return $data;
        }
    }

    /**
     * 替换枚举
     *
     * @param $obj
     * @param array $target
     * @return bool
     *
     * create by ck 20170817
     */
    public static function runEnum(&$obj, $target = [])
    {
        if (!$obj || !$target) {
            return false;
        }
        is_object($obj) and $obj = (array)$obj;
        foreach ($target as $field => $enum) {
            if (isset($obj[$field]) && isset($enum[$obj[$field]])) {
                $obj[$field] = $enum[$obj[$field]];
            }
        }
        if (@is_array(end($obj))) {
            foreach ($obj as $index => $item) {
                self::runEnum($obj[$index], $target);
            }
        }
        return true;
    }

    /**
     * 根据枚举数组及目标数组替换时间戳为日期类型
     *
     * @param $obj
     * @param string|array $target
     * @param $dealMicro
     * @param string $format
     * @return bool
     *
     * create by ck 20170817
     * modify by ck 20180831
     * modify by ck 20181016    时间戳为0时转化为''
     */
    public static function runTimestamp(&$obj, $target = [], $dealMicro = true, $format = 'Y-m-d H:i:s')
    {
        if (!$obj || !$target) {
            return false;
        }
        is_string($target) and $target = [$target];
        foreach ($target as $field) {
            if (isset($obj[$field])) {
                if (!$obj[$field]) {
                    $obj[$field] = '';
                    continue;
                }
                $obj[$field] = date($format, $dealMicro ? substr($obj[$field], 0, 10) : $obj[$field]);
            }
        }
        if (@is_array(end($obj))) {
            foreach ($obj as $index => $item) {
                self::runTimestamp($obj[$index], $target, $dealMicro, $format);
            }
        }
        return true;
    }

    /**
     * 根据枚举数组及目标数组替换枚举值为int型
     *
     * @param $obj
     * @param array $target
     * @return bool
     *
     * create by ck 20170817
     */
    public static function runInteger(&$obj, $target = [])
    {
        if (!$obj || !$target) {
            return false;
        }
        is_string($target) and $target = [$target];
        foreach ($target as $field) {
            if (isset($obj[$field])) {
                $obj[$field] = intval($obj[$field]);
            }
        }
        if (@is_array(end($obj))) {
            foreach ($obj as $index => $item) {
                self::runInteger($obj[$index], $target);
            }
        }
        return true;
    }

    /**
     * 根据枚举数组及目标数组替换枚举值为bool型
     *
     * @param $obj
     * @param array $target
     * @return bool
     *
     * create by ck 20181016
     */
    public static function runBoolean(&$obj, $target = [])
    {
        if (!$obj || !$target) {
            return false;
        }
        is_string($target) and $target = [$target];
        foreach ($target as $field) {
            if (isset($obj[$field])) {
                $obj[$field] = $obj[$field] == 'true' ? true : false;
            }
        }
        if (@is_array(end($obj))) {
            foreach ($obj as $index => $item) {
                self::runInteger($obj[$index], $target);
            }
        }
        return true;
    }

    /**
     * 根据枚举数组及目标数组替换秒为中文时长
     *
     * @param $obj
     * @param array $target
     * @return bool
     *
     * create by ck 20180308
     */
    public static function runTimeToStr(&$obj, $target = [])
    {
        if (!$obj || !$target) {
            return false;
        }
        is_string($target) and $target = [$target];
        foreach ($target as $field) {
            if (isset($obj[$field])) {
                $obj[$field] = self::secondToTime($obj[$field]);
            }
        }
        if (@is_array(end($obj))) {
            foreach ($obj as $index => $item) {
                self::runTimeToStr($obj[$index], $target);
            }
        }
        return true;
    }

    /**
     * 将数组对应的文件大小值从Byte转为MB
     *
     * @param $obj
     * @param $targetArr
     *
     * create by ck 20161218
     */
    public static function runByteToMByte(&$obj, $targetArr)
    {
        is_string($targetArr) and $targetArr = [$targetArr];
        foreach ($obj as $key => $value) {
            foreach ($targetArr as $target) {
                isset($value[$target]) and $obj[$key][$target] = round($value[$target] / (1024 * 1024), 3) . ' M';
            }
        }
    }

    /**
     * 秒转换为中文时间字符串
     *
     * @param $second
     * @return bool|string
     *
     * create by ck 20170108
     * modify by ck 20170510    处理带逗号数字
     */
    public static function secondToTime($second)
    {
        $second = str_replace(',', '', $second);
        if (is_numeric($second)) {
            $value = array(
                'years' => 0,
                'days' => 0,
                'hours' => 0,
                'minutes' => 0,
                'seconds' => 0,
            );
            if ($second >= 31556926) {
                $value['years'] = floor($second / 31556926);
                $second = ($second % 31556926);
            }
            if ($second >= 86400) {
                $value['days'] = floor($second / 86400);
                $second = ($second % 86400);
            }
            if ($second >= 3600) {
                $value['hours'] = floor($second / 3600);
                $second = ($second % 3600);
            }
            if ($second >= 60) {
                $value['minutes'] = floor($second / 60);
                $second = ($second % 60);
            }
            $value['seconds'] = floor($second);
            $t = '';
            if ($value['years']) {
                $t = $t . $value['years'] . '年';
            }
            if ($value['days']) {
                $t = $t . $value['days'] . '天';
            }
            if ($value['hours']) {
                $t = $t . $value['hours'] . '小时';
            }
            if ($value['minutes']) {
                $t = $t . $value['minutes'] . '分';
            }
            if ($value['seconds']) {
                $t = $t . $value['seconds'] . '秒';
            }
            return $t;
        } else {
            return '';
        }
    }

    /**
     * 创建zip包
     *
     * @param $zipName      --zip文件名
     * @param $path         --压缩文件夹路径
     * @return bool|string
     *
     * create by ck 20170504
     */
    public static function createZipFile($zipName, $path)
    {
        //windows则处理编码
        if (PATH_SEPARATOR == ';') {
            $zipName = iconv('utf-8', 'GBK', $zipName);
            $path = iconv('utf-8', 'GBK', $path);
        }
        $zipDir = dirname($zipName);
        if (!is_writable($zipDir)) {
            return $zipName . '路径不可写！';
        }
        if (!is_dir($path)) {
            return $path . '非正常路径！';
        }
        if (!is_readable($path)) {
            return $path . '路径不可读！';
        }
        //防止OVERWRITE模式不生效
        is_file($zipName) and @unlink($zipName);
        $zip = new \ZipArchive();
        $res = $zip->open($zipName, \ZIPARCHIVE::CREATE);
        if ($res !== true) {
            return $zipName . '打开失败！';
        }
        self::addFileToZip($path, $zip);
        $zip->close();
        return true;
    }

    /**
     * 根据路径将文件夹递归写入压缩包
     *
     * @param $path
     * @param \ZipArchive $zip
     *
     * create by ck 20170504
     */
    private static function addFileToZip($path, \ZipArchive $zip)
    {
        //记录主目录路径
        static $sourcePath;
        if (empty($sourcePath)) {
            $sourcePath = $path;
        }
        //打开当前文件夹由$path指定。
        $handler = opendir($path);
        while (($filename = readdir($handler)) !== false) {
            //文件夹文件名字为'.'和‘..’，不要对他们进行操作
            if ($filename == '.' || $filename == '..') {
                continue;
            }
            $filename = $path . '/' . $filename;
            //如果读取的某个对象是文件夹则递归，否则加入zip
            if (is_dir($filename)) {
                self::addFileToZip($filename, $zip);
            } else {
                //防止路径写入zip
                $localName = ltrim(str_replace($sourcePath, '', $filename), '/');
                $zip->addFile($filename, $localName);
            }
        }
        @closedir($path);
    }

    /**
     * 删除目录及文件
     *
     * @param $dirName
     * @return bool
     *
     * create by ck 20160923
     */
    public static function delDirAndFile($dirName){
        if($handle = @opendir($dirName)){
            while(false !== ($item = readdir($handle))){
                if($item != "." && $item != ".."){
                    if(is_dir("$dirName/$item")){
                        self::delDirAndFile("$dirName/$item");
                    }else{
                        if(!unlink("$dirName/$item")) return false;
                    }
                }
            }
            closedir($handle);
            if(rmdir($dirName)) return true;
        }
        return false;
    }

    /**
     * 获取随机数
     *
     * @param int $len
     * @param string $format
     * @return string
     *
     * create by ck 20180208
     */
    public static function getRand($len = 6, $format = 'NUMBER'){
        $isStr = $isNum = 0;
        $randNum = $tmp ='';
        switch($format){
            case 'ALL':
                $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
                break;
            case 'CHAR':
                $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
                break;
            case 'NUMBER':
                $chars='0123456789';
                break;
            default :
                $chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
                break;
        }
//        mt_srand((double)microtime()*1000000*getmypid());
        while(strlen($randNum)<$len){
            $tmp =substr($chars,(mt_rand()%strlen($chars)),1);
            if(($isNum <> 1 && is_numeric($tmp) && $tmp > 0 )|| $format == 'CHAR'){
                $isNum = 1;
            }
            if(($isStr <> 1 && preg_match('/[a-zA-Z]/',$tmp)) || $format == 'NUMBER'){
                $isStr = 1;
            }
//            if($format == 'NUMBER' && $randNum==0){
//                $randNum += 1;
//            }
            $randNum.= $tmp;
        }
        if($isNum <> 1 || $isStr <> 1 || empty($randNum) ){
            $randNum = self::getRand($len, $format);
        }
        return $randNum;
    }

    /**
     * 根据验证码生成验证图片
     *
     * @param $captchaCode
     *
     * create by ck 20180330
     */
//    public static function createCaptchaImage($captchaCode)
//    {
//        $image      = imagecreatetruecolor(100, 30);
//        $bgColor    = imagecolorallocate($image,255,255,255); //#ffffff
//        $codeCount  = strlen($captchaCode);
//        imagefill($image, 0, 0, $bgColor);
//        for ($i = 0; $i < $codeCount; $i++) {
//            $fontSize  = 5;
//            $fontColor = imagecolorallocate($image, rand(0,120),rand(0,120), rand(0,120));
//            $x         = ($i * 100 / $codeCount) + rand(5,10);
//            $y         = rand(5,10);
////            $fontColor = imagecolorallocate($image, 0, 153, 204);
////            $y         = rand(20, 30);
////            imagettftext($image, $fontSize, rand(-20, 20), $x, $y, $fontColor, 'Jackey_Egypt.ttf', $captchaCode[$i]);
//            imagestring($image, $fontSize, $x, $y, $captchaCode[$i], $fontColor);
//        }
//        //增加干扰元素，设置雪花点
//        for ($i = 0; $i < 200; $i++) {
//            //设置点的颜色，50-200颜色比数字浅，不干扰阅读
//            $pointColor = imagecolorallocate($image,rand(50,200), rand(50,200), rand(50,200));
//            imagesetpixel($image, rand(1,99), rand(1,29), $pointColor);
//        }
//        //增加干扰元素，设置横线
//        for ($i = 0; $i < 4; $i++) {
//            //设置线的颜色
//            $lineColor = imagecolorallocate($image, rand(80,220), rand(80,220), rand(80,220));
//            //设置线，两点一线
//            imageline($image, rand(1,99), rand(1,29), rand(1,99), rand(1,29), $lineColor);
//        }
//        //输出
//        header('Pragma: no-cache');
//        header('Content-Type: image/png');
//        imagepng($image);
//        imagedestroy($image);
//    }

    /**
     * 获取IP地址
     *
     * @return array|false|string
     *
     * create by ck 20180409
     * modify by dale 20190218 多个ip取最后一个
     */
    public static function getIp()
    {
        $ip = "unknown";
        if (isset($_SERVER)) {
            if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
                $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
            } elseif (isset($_SERVER["HTTP_CLIENT_ip"])) {
                $ip = $_SERVER["HTTP_CLIENT_ip"];
            } elseif (isset($_SERVER["HTTP_CLIENT_ip"])) {
                $ip = $_SERVER["HTTP_CLIENT_ip"];
            } else {
                $ip = $_SERVER["REMOTE_ADDR"];
            }
        } else {
            if (getenv('HTTP_X_FORWARDED_FOR')) {
                $ip = getenv('HTTP_X_FORWARDED_FOR');
            } elseif (getenv('HTTP_CLIENT_ip')) {
                $ip = getenv('HTTP_CLIENT_ip');
            } else {
                $ip = getenv('REMOTE_ADDR');
            }
        }
        if (trim($ip) == "::1") {
            $ip = "127.0.0.1";
        }
        if (is_string($ip)) {
            $ips = explode(',', $ip);
            $ip = end($ips);
        } elseif (is_array($ip)) {
            $ip = end($ip);
        }
        return $ip;
    }

    /**
     * 读取浏览器名称及型号
     *
     * @return string
     *
     * create by ck 20160305
     */
    public static function getBrowser()
    {
        $sys = @$_SERVER['HTTP_USER_AGENT'];  //获取用户代理字符串
        if (stripos($sys, "Firefox/") > 0) {
            preg_match("/Firefox\/([^;)]+)+/i", $sys, $b);
            $exp[0] = "Firefox";
            $exp[1] = $b[1];  //获取火狐浏览器的版本号
        } elseif (stripos($sys, "Maxthon") > 0) {
            preg_match("/Maxthon\/([\d\.]+)/", $sys, $aoyou);
            $exp[0] = "傲游";
            $exp[1] = $aoyou[1];
        } elseif (stripos($sys, "MSIE") > 0) {
            preg_match("/MSIE\s+([^;)]+)+/i", $sys, $ie);
            $exp[0] = "IE";
            $exp[1] = $ie[1];  //获取IE的版本号
        } elseif (stripos($sys, "OPR") > 0) {
            preg_match("/OPR\/([\d\.]+)/", $sys, $opera);
            $exp[0] = "Opera";
            $exp[1] = $opera[1];
        } elseif(stripos($sys, "Edge") > 0) {
            //win10 Edge浏览器 添加了chrome内核标记 在判断Chrome之前匹配
            preg_match("/Edge\/([\d\.]+)/", $sys, $Edge);
            $exp[0] = "Edge";
            $exp[1] = $Edge[1];
        } elseif (stripos($sys, "Chrome") > 0) {
            preg_match("/Chrome\/([\d\.]+)/", $sys, $google);
            $exp[0] = "Chrome";
            $exp[1] = $google[1];  //获取google chrome的版本号
        } elseif(stripos($sys,'rv:')>0 && stripos($sys,'Gecko')>0){
            preg_match("/rv:([\d\.]+)/", $sys, $IE);
            $exp[0] = "IE";
            $exp[1] = $IE[1];
        }else {
            $exp[0] = "未知浏览器";
            $exp[1] = "";
        }
        return $exp[0].'('.$exp[1].')';
    }

    /**
     * 读取操作系统名称及版本
     *
     * @return string
     *
     * create by ck 20160305
     */
    public static function getOS()
    {
        $agent = @$_SERVER['HTTP_USER_AGENT'];
        if (preg_match('/win/i', $agent) && strpos($agent, '95'))
        {
            $os = 'Windows 95';
        }
        else if (preg_match('/win 9x/i', $agent) && strpos($agent, '4.90'))
        {
            $os = 'Windows ME';
        }
//        else if (preg_match('/win/i', $agent) && preg_match('/98/i', $agent))
//        {
//            $os = 'Windows 98';
//        }
        else if (preg_match('/win/i', $agent) && preg_match('/nt 6.0/i', $agent))
        {
            $os = 'Windows Vista';
        }
        else if (preg_match('/win/i', $agent) && preg_match('/nt 6.1/i', $agent))
        {
            $os = 'Windows 7';
        }
        else if (preg_match('/win/i', $agent) && preg_match('/nt 6.2/i', $agent))
        {
            $os = 'Windows 8';
        }else if(preg_match('/win/i', $agent) && preg_match('/nt 10.0/i', $agent))
        {
            $os = 'Windows 10';#添加win10判断
        }else if (preg_match('/win/i', $agent) && preg_match('/nt 5.1/i', $agent))
        {
            $os = 'Windows XP';
        }
        else if (preg_match('/win/i', $agent) && preg_match('/nt 5/i', $agent))
        {
            $os = 'Windows 2000';
        }
        else if (preg_match('/win/i', $agent) && preg_match('/nt/i', $agent))
        {
            $os = 'Windows NT';
        }
        else if (preg_match('/win/i', $agent) && preg_match('/32/i', $agent))
        {
            $os = 'Windows 32';
        }
        else if (preg_match('/linux/i', $agent))
        {
            $os = 'Linux';
        }
        else if (preg_match('/unix/i', $agent))
        {
            $os = 'Unix';
        }
        else if (preg_match('/sun/i', $agent) && preg_match('/os/i', $agent))
        {
            $os = 'SunOS';
        }
        else if (preg_match('/ibm/i', $agent) && preg_match('/os/i', $agent))
        {
            $os = 'IBM OS/2';
        }
        else if (preg_match('/Mac/i', $agent) && preg_match('/PC/i', $agent))
        {
            $os = 'Macintosh';
        }
        else if (preg_match('/PowerPC/i', $agent))
        {
            $os = 'PowerPC';
        }
        else if (preg_match('/AIX/i', $agent))
        {
            $os = 'AIX';
        }
        else if (preg_match('/HPUX/i', $agent))
        {
            $os = 'HPUX';
        }
        else if (preg_match('/NetBSD/i', $agent))
        {
            $os = 'NetBSD';
        }
        else if (preg_match('/BSD/i', $agent))
        {
            $os = 'BSD';
        }
        else if (preg_match('/OSF1/i', $agent))
        {
            $os = 'OSF1';
        }
        else if (preg_match('/IRIX/i', $agent))
        {
            $os = 'IRIX';
        }
        else if (preg_match('/FreeBSD/i', $agent))
        {
            $os = 'FreeBSD';
        }
        else if (preg_match('/teleport/i', $agent))
        {
            $os = 'teleport';
        }
        else if (preg_match('/flashget/i', $agent))
        {
            $os = 'flashget';
        }
        else if (preg_match('/webzip/i', $agent))
        {
            $os = 'webzip';
        }
        else if (preg_match('/offline/i', $agent))
        {
            $os = 'offline';
        }
        else
        {
            $os = '未知操作系统';
        }
        return $os;
    }

    /**
     * 根据枚举数组及目标数组替换时间戳为日期类型
     *
     * @param $obj
     * @param array $enumArr
     * @param bool $isArray
     *
     * create by ck 20170704
     */
//    public static function runEnumTimestamp(&$obj, $enumArr = [], $isArray = true)
//    {
//        if($isArray){
//            foreach($obj as $index => $row){
//                foreach($enumArr as $field){
//                    if(!isset($row[$field])) continue;
//                    $obj[$index][$field] = $row[$field] ? date('Y-m-d H:i:s', substr($row[$field], 0, 10)) : '';
//                }
//            }
//        }
//        else{
//            foreach($enumArr as $field){
//                if(!isset($obj[$field])) continue;
//                $obj[$field] = $obj[$field] ? date('Y-m-d H:i:s', substr($obj[$field], 0, 10)) : '';
//            }
//        }
//    }

    /**
     * 根据枚举数组及目标数组替换枚举值为int型
     *
     * @param $obj
     * @param array $enumArr
     * @param bool $isArray
     *
     * create by ck 20170701
     */
//    public static function runEnumInteger(&$obj, $enumArr = [], $isArray = true)
//    {
//        if($isArray){
//            foreach($obj as $index => $row){
//                foreach($enumArr as $field => $enum){
//                    if(!isset($row[$field])) continue;
//                    $obj[$index][$field] = intval($row[$field]);
//                }
//            }
//        }
//        else{
//            foreach($enumArr as $field => $enum){
//                if(!isset($obj[$field])) continue;
//                $obj[$field] = intval($obj[$field]);
//            }
//        }
//    }

    /**
     * 根据枚举数组及目标数组替换枚举值
     *
     * @param $obj
     * @param array $enumArr
     * @param $isArray
     *
     * create by ck 20170629
     * modify by ck 20170701    非数组且为对象时自动转化为数组
     */
//    public static function runEnumField(&$obj, $enumArr = [], $isArray = true)
//    {
//        if($isArray){
//            foreach($obj as $index => $row){
//                foreach($enumArr as $field => $enum){
//                    if(!isset($row[$field])) continue;
//                    @$obj[$index][$field] = $enum[$row[$field]];
//                }
//            }
//        }
//        else{
//            is_object($obj) and $obj = (array)$obj;
//            foreach($enumArr as $field => $enum){
//                if(!isset($obj[$field])) continue;
//                @$obj[$field] = $enum[$obj[$field]];
//            }
//        }
//    }

}

